﻿using MyPetShop.Domain;
using Microsoft.Practices.ServiceLocation;
using MyPetShop.Domain.Exception;
using NCommon.Data;
using System.Linq;
using NCommon.Events;
using NUnit.Framework;
using NCommon.Specifications;
using Rhino.Mocks;
using NCommon.Rules;
using NCommon.State;
using NCommon.State.Impl;

namespace MyPetShop.Domain.Spec
{
	[TestFixture]
	public class CheckOut_Order
    {
		
		[Test]
        [ExpectedException(typeof(OverStockException))]
		public void CheckQuantityOfShopping()
		{
			OrderService orderService = new OrderService();
			var item = new Item();
            item.ItemId = 1;
            item.ListPrice = 100;
            item.Quantity = 10;
			
			var shopping = new Shopping();
            shopping.AddItem(item, 11);
			
			MockRepository mocks = new MockRepository();
			IServiceLocator serviceLocator = mocks.StrictMock<IServiceLocator>();
			ServiceLocator.SetLocatorProvider(() => serviceLocator);
			
			var validator = new ShoppingDetailOverStockValidator();
			var itemRepository = new FakeRepository<Item>();
			itemRepository.Add(item);
			
            using(mocks.Record())
            {
                serviceLocator.Expect(s => s.GetInstance<IValidationRule<ShoppingDetail>>("OverStockValidate")).Return(validator);
                serviceLocator.Expect(s => s.GetInstance<IRepository<Item>>()).Return(itemRepository);
			}
			
            using(mocks.Playback())
            {
			    orderService.CheckOut(shopping);
			}
		}

		[Test]
		public void MakeOrderFromShoppingAndDecreaseQuantiryOfItem()
		{
			OrderService orderService = new OrderService();
			Shopping shopping = new Shopping();
			Item item = new Item();
			item.ItemId = 1;
		    item.ListPrice = 100;
			item.Quantity = 19;
			shopping.AddItem(item,10);

			MockRepository mocks = new MockRepository();
			IServiceLocator serviceLocator = mocks.StrictMock<IServiceLocator>();
			ServiceLocator.SetLocatorProvider(() => serviceLocator);
            
            var validator = new ShoppingDetailOverStockValidator();
            var orderRepository = new FakeRepository<Order>();
            var itemRepository = new FakeRepository<Item>();
            itemRepository.Add(item);
            var orderCreatedHandler = new OrderCreateEventHandler();            
            var state = new State(null,new ThreadLocalState(),null,null);
            	
			using(mocks.Record())
			{
				serviceLocator.Expect(s => s.GetInstance<IValidationRule<ShoppingDetail>>("OverStockValidate")).Return(validator);
				serviceLocator.Expect(s => s.GetInstance<IRepository<Item>>()).Return(itemRepository).Repeat.Twice();
				serviceLocator.Expect(s => s.GetInstance<IRepository<Order>>()).Return(orderRepository);
				serviceLocator.Expect(s => s.GetInstance<IState>()).Return(state);
				serviceLocator.Expect(s => s.GetAllInstances<Handles<OrderCreateEvent>>()).Return(new []{orderCreatedHandler});
			}
			
			using(mocks.Playback())
			{
				orderService.CheckOut(shopping);
			}
			
			Assert.AreEqual(1,orderRepository.Count);
			Assert.AreEqual(9,item.Quantity);
		}
		
	    #region Unit Test
	    public void AddShoppingDetailIntoShopping()
	    {
	    	
	    }
	    
	    public void AddOrderDetailIntoOrder()
	    {
	    
	    }
	    
	    public void MakeOrder_OrderFactory()
	    {
	    	Order order = OrderFactory.MakeOrder(new Shopping());
	    }
	    
	    [Test]
	    public void OrderCreatedEventHandler()
	    {
	    	Order order = new Order();
	    	OrderDetail orderDetail = new OrderDetail()
	    	{
	    		ItemId = 1,
	    		OrderDetailId = 1,
	    		Quantity = 10,
	    		SellPrice = 300
	    	};
	    	Item item = new Item()
	    	{
	    		ItemId = 1,
	    		Quantity = 20,
	    		ListPrice = 300
	    	};
	    	
	    	order.AddOrderDetail(orderDetail);

            MockRepository mocks = new MockRepository();
            
            IServiceLocator serviceLocator = mocks.DynamicMock<IServiceLocator>();
            ServiceLocator.SetLocatorProvider(() => serviceLocator);
            
            IRepository<Item> itemRepository = new FakeRepository<Item>();
            itemRepository.Add(item);
	    	
            using(mocks.Record())
            {
            	serviceLocator.Expect(s=>s.GetInstance<IRepository<Item>>()).Return(itemRepository);
	    	}
            
            using(mocks.Playback())
            {
            	OrderCreateEventHandler handler = new OrderCreateEventHandler();
            	handler.Handle(new OrderCreateEvent(order));
            }
	    	
            Assert.AreEqual(10,item.Quantity);
	    }
	    #endregion
    }
}
